package com.cyys.common.thirdInterface.wx;

import com.alibaba.fastjson.JSONException;
import com.alibaba.fastjson.JSONObject;
import com.cyys.common.ql.AR;
import com.cyys.common.thirdInterface.CommonUtil;
import com.cyys.common.thirdInterface.PayUtil;
import com.cyys.common.thirdInterface.ThirdConfig;
import com.cyys.common.thirdInterface.wx.config.WxConfig;
import com.cyys.common.utils.StringUtil;
import org.apache.http.HttpEntity;
import org.apache.http.HttpException;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.ByteArrayEntity;
import org.apache.http.entity.ContentType;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;
import org.springframework.util.StringUtils;
import org.springframework.web.multipart.MultipartFile;

import java.io.InputStream;
import java.util.HashMap;
import java.util.Map;

public class WxNoun {

    public static Map<String, Object> unifiedorder(String body, String orderNo, String openId, String ip, String money)
            throws Exception {
        // 小程序订单生成
        // 生成的随机字符串
        String nonce_str = StringUtil.getRandom(32);

        Map<String, String> packageParams = new HashMap<>();
        packageParams.put("appid", ThirdConfig.WX_APP_ID);
        packageParams.put("mch_id", ThirdConfig.WX_MCH_ID);
        packageParams.put("nonce_str", nonce_str);
        packageParams.put("body", body);
        packageParams.put("out_trade_no", orderNo);// 商户订单号
        packageParams.put("total_fee", money);// 支付金额，这边需要转成字符串类型，否则后面的签名会失败
        packageParams.put("spbill_create_ip", ip);
        packageParams.put("notify_url", WxConfig.NOTIFY_URL);
        packageParams.put("trade_type", WxConfig.TRADE_TYPE);
        packageParams.put("openid", openId);

        // 除去数组中的空值和签名参数
        packageParams = PayUtil.paraFilter(packageParams);
        String prestr = PayUtil.createLinkString(packageParams); // 把数组所有元素，按照“参数=参数值”的模式用“&”字符拼接成字符串

        // MD5运算生成签名，这里是第一次签名，用于调用统一下单接口
        String mysign = PayUtil.sign(prestr, ThirdConfig.WX_MCH_KEY, "utf-8").toUpperCase();

        // 拼接统一下单接口使用的xml数据，要将上一步生成的签名一起拼接进去
        String xml = "<xml>" + "<appid>" + ThirdConfig.WX_APP_ID + "</appid>" + "<body><![CDATA[" + body + "]]></body>"
                + "<mch_id>" + ThirdConfig.WX_MCH_ID + "</mch_id>" + "<nonce_str>" + nonce_str + "</nonce_str>"
                + "<notify_url>" + WxConfig.NOTIFY_URL + "</notify_url>" + "<openid>" + openId + "</openid>"
                + "<out_trade_no>" + orderNo + "</out_trade_no>" + "<spbill_create_ip>" + ip + "</spbill_create_ip>"
                + "<total_fee>" + money + "</total_fee>" + "<trade_type>" + WxConfig.TRADE_TYPE + "</trade_type>"
                + "<sign>" + mysign + "</sign>" + "</xml>";

        // System.out.println("调试模式_统一下单接口 请求XML数据：" + xml);

        // 调用统一下单接口，并接受返回的结果
        String result = PayUtil.httpRequest(WxConfig.PAY_URL, "POST", xml);

        // 将解析结果存储在HashMap中
        Map<String, String> map = PayUtil.doXMLParse(result);

        String return_code =  map.get("return_code");// 返回状态码

        // 返回给移动端需要的参数
        Map<String, Object> wxParam = new HashMap<String, Object>();
        if (return_code.equals("SUCCESS")) {
            // 业务结果
            String prepay_id = map.get("prepay_id");// 返回的预付单信息
            wxParam.put("nonceStr", nonce_str);
            wxParam.put("package", "prepay_id=" + prepay_id);
            Long timeStamp = System.currentTimeMillis() / 1000;
            wxParam.put("timeStamp", timeStamp + "");// 这边要将返回的时间戳转化成字符串，不然小程序端调用wx.requestPayment方法会报签名错误

            String stringSignTemp = "appId=" + ThirdConfig.WX_APP_ID + "&nonceStr=" + nonce_str + "&package=prepay_id="
                    + prepay_id + "&signType=" + WxConfig.SIGN_TYPE + "&timeStamp=" + timeStamp;
            // 再次签名，这个签名用于小程序端调用wx.requesetPayment方法
            String paySign = PayUtil.sign(stringSignTemp, ThirdConfig.WX_MCH_KEY, "utf-8").toUpperCase();
            // logger.info("=======================第二次签名：" + paySign +
            // "=====================");
            wxParam.put("paySign", paySign);
        } else {
            wxParam.put("msg", map.get("return_msg"));
        }
        wxParam.put("appid", ThirdConfig.WX_APP_ID);
        wxParam.put("return_code", return_code);
        return wxParam;
    }

    public static Map<String, Object> refund(String orderNo, String outTradeNo, String refundNo, String money)
            throws Exception {
        // 生成的随机字符串
        String nonce_str = StringUtil.getRandom(32);

        Map<String, String> refundParams = new HashMap<String, String>();
        refundParams.put("appid", ThirdConfig.WX_APP_ID);
        refundParams.put("mch_id", ThirdConfig.WX_MCH_ID);
        refundParams.put("nonce_str", nonce_str);
        refundParams.put("out_refund_no", refundNo);// 商户退款单号
        refundParams.put("out_trade_no", orderNo);// 商户订单号
        refundParams.put("refund_fee", money);// 退款金额，这边需要转成字符串类型，否则后面的签名会失败
        refundParams.put("total_fee", money);// 订单金额，这边需要转成字符串类型，否则后面的签名会失败
        refundParams.put("refund_account", WxConfig.REFUND_ACCOUNT);  //退款资金来源
        refundParams.put("transaction_id", outTradeNo); //微信付款订单号（第三方支付订单流水号）
        refundParams.put("notify_url", WxConfig.REFUND_NOTIFY_URL);

        // 除去数组中的空值和签名参数
        refundParams = PayUtil.paraFilter(refundParams);
        String prestr = PayUtil.createLinkString(refundParams); // 把数组所有元素，按照“参数=参数值”的模式用“&”字符拼接成字符串

        // MD5运算生成签名
        String refundSign = PayUtil.sign(prestr, ThirdConfig.WX_MCH_KEY, "utf-8").toUpperCase();

        // 拼接统一下单接口使用的xml数据，要将上一步生成的签名一起拼接进去
        String xml = "<xml>"
                + "<appid>" + ThirdConfig.WX_APP_ID + "</appid>"
                + "<mch_id>" + ThirdConfig.WX_MCH_ID + "</mch_id>"
                + "<nonce_str>" + nonce_str + "</nonce_str>"
                + "<out_refund_no>" + refundNo + "</out_refund_no>"
                + "<out_trade_no>" + orderNo + "</out_trade_no>"
                + "<refund_fee>" + money + "</refund_fee>"
                + "<total_fee>" + money + "</total_fee>"
                + "<refund_account>" + WxConfig.REFUND_ACCOUNT + "</refund_account>"
                + "<transaction_id>" + outTradeNo+ "</transaction_id>"
                + "<notify_url>" + WxConfig.REFUND_NOTIFY_URL + "</notify_url>"
                + "<sign>" + refundSign + "</sign>" + "</xml>";


        // 调用申请退款接口，并接受返回的结果
        String certUrl = WxConfig.REFUND_APICLIENT_CERT;
        String result = PayUtil.doRefund(certUrl, ThirdConfig.WX_MCH_ID, WxConfig.REFUND_URL, xml); //ThirdConfig.WX_MCH_ID; 证书默认密码
        System.out.println("=======调用申请退款接口 返回结果："+result);
        // 将解析结果存储在HashMap中
        Map<String, String> map = PayUtil.doXMLParse(result);

        String return_code =  map.get("return_code");// 返回状态码

        Map<String, Object> wxParam = new HashMap<String, Object>();
        if (return_code.equals("SUCCESS")) {
            // 业务结果
            String refund_id =  map.get("refund_id");// 返回的微信退款单号
            wxParam.put("refund_id", refund_id);
        } else {
            wxParam.put("msg",  map.get("return_msg"));
        }
        wxParam.put("appid", ThirdConfig.WX_APP_ID);
        wxParam.put("return_code", return_code);
        return wxParam;
    }

//    /**
//     * @param basePath
//     * @param id
//     * @param type
//     * @return
//     */
//    public static AjaxJson getWxacodeunlimit(String basePath, Long id, Integer type) {
//        AjaxJson aj = new AjaxJson();
//        String accessToken = WxNoun.getToken();
//        if (accessToken == null) {
//            aj.setSuccess(false);
//            aj.setMsg("获取token失败");
//            return aj;
//        }
//        String requestUrl = WxConfig.WXACODE_URL_C.replace("ACCESS_TOKEN", accessToken);
//        String path = "";
//        if (type == 1) { // 音频
//            path = "pages/previewGeneral/previewGeneral?id=" + id;
//        } else if (type == 2) { // 视频
//            path = "pages/previewVideo/previewVideo?id=" + id;
//        }
//        String postParam = "{\"path\": \"" + path + "\", \"width\": 430}";
//
//        // logger.info(requestUrl);
//        // 发起GET请求获取凭证
//        return CommonUtil.httpsRequestStream(requestUrl, "POST", postParam, basePath, id);
//    }
    /**
     * @param code
     * @return
     */
    public static AR jscode2session(String code) {
        if (StringUtils.isEmpty(code)) {
            return AR.failed("code为空");
        } else {
            String requestUrl = WxConfig.WX_URL.replace("APPID", ThirdConfig.WX_APP_ID)
                    .replace("SECRET", ThirdConfig.WX_APP_SECRECT).replace("JSCODE", code)
                    .replace("authorization_code", WxConfig.AUTHORIZATION_CODE);
            // logger.info(requestUrl);
            // 发起GET请求获取凭证
            JSONObject jsonObject = CommonUtil.httpsRequest(requestUrl, "GET", null);
            if (jsonObject != null) {
                try {
                    Map<String,String> map = new HashMap<>();
                    map.put("openid", jsonObject.getString("openid"));
                    map.put("session_key", jsonObject.getString("session_key"));
                    return AR.ok(map,"获取成功");
                } catch (JSONException e) {
                    return AR.failed("code无效");
                }
            } else {
                return AR.failed("code无效");
            }
        }
    }

    /**
     * 查询订单支付结果
     * @param outTradeNo 商户订单号
     * @return
     * @throws Exception
     */
    public static Map<String, String> orderquery(String outTradeNo)
            throws Exception {
        // 生成的随机字符串
        String nonce_str = StringUtil.getRandom(32);

        Map<String, String> packageParams = new HashMap<String, String>();
        packageParams.put("appid", ThirdConfig.WX_APP_ID);
        packageParams.put("mch_id", ThirdConfig.WX_MCH_ID);
        packageParams.put("nonce_str", nonce_str);
        packageParams.put("out_trade_no", outTradeNo);// 商户订单号

        // 除去数组中的空值和签名参数
        packageParams = PayUtil.paraFilter(packageParams);
        String prestr = PayUtil.createLinkString(packageParams); // 把数组所有元素，按照“参数=参数值”的模式用“&”字符拼接成字符串

        // MD5运算生成签名，这里是第一次签名，用于调用订单查询接口
        String mysign = PayUtil.sign(prestr, ThirdConfig.WX_MCH_KEY, "utf-8").toUpperCase();

        // 拼接订单查询接口使用的xml数据，要将上一步生成的签名一起拼接进去
        String xml = "<xml>" + "<appid>" + ThirdConfig.WX_APP_ID + "</appid>"
                + "<mch_id>" + ThirdConfig.WX_MCH_ID + "</mch_id>"
                + "<nonce_str>" + nonce_str + "</nonce_str>"
                + "<out_trade_no>" + outTradeNo + "</out_trade_no>"
                + "<sign>" + mysign + "</sign>" + "</xml>";

        // 调用订单查询接口，并接受返回的结果
        String result = PayUtil.httpRequest(WxConfig.PAY_QUERY_URL, "POST", xml);

        // System.out.println("调试模式_统一下单接口 返回XML数据：" + result);

        // 将解析结果存储在HashMap中

        Map<String, String> map = PayUtil.doXMLParse(result);

        String return_code =  map.get("return_code");// 返回状态码

        // 返回给移动端需要的参数
        Map<String, String> wxParam = new HashMap<String, String>();
        if (return_code.equals("SUCCESS")) {
            // 业务结果
            wxParam.put("trade_state",  map.get("trade_state"));// 交易状态
            wxParam.put("trade_state_desc", map.get("trade_state_desc"));// 交易状态描述
            wxParam.put("transaction_id", map.get("transaction_id")); //微信支付订单号
            wxParam.put("time_end", map.get("time_end"));
        } else {
            wxParam.put("return_msg", map.get("return_msg"));
        }
        return wxParam;
    }


    /**
     * @return
     */
    public static String getToken() {
        String requestUrl = WxConfig.TOKEN_URL.replace("APPID", ThirdConfig.WX_APP_ID).replace("APPSECRET",
                ThirdConfig.WX_APP_SECRECT);
        // logger.info(requestUrl);
        // 发起GET请求获取凭证
        JSONObject jsonObject = CommonUtil.httpsRequest(requestUrl, "GET", null);
        if (jsonObject != null) {
            if (jsonObject.getString("errcode") == null) {
                return jsonObject.getString("access_token");
            } else {
                return null;
            }
        } else {
            return null;
        }
    }

    public static Boolean checkMsg(String content) throws HttpException {
        String accessToken = getToken();
        String requestUrl = WxConfig.MSG_SEC_CHECK.replace("MSG_SEC_CHECK", accessToken);

        String postStr = "{\"content\": \"" + content + "\"}";
        // 发起GET请求获取凭证
        JSONObject jsonObject = CommonUtil.httpsRequest(requestUrl, "POST", postStr);
        if (jsonObject != null) {
            System.out.println(jsonObject.getString("errmsg"));
            if (jsonObject.getInteger("errcode") == 0) {
                return true;
            } else {
                return false;
            }
        } else {
            return false;
        }
    }

    public static Boolean checkImg(MultipartFile file) throws HttpException {
        try {
            CloseableHttpClient httpclient = HttpClients.createDefault();
            CloseableHttpResponse response = null;
            HttpPost request = new HttpPost("https://api.weixin.qq.com/wxa/img_sec_check?access_token=" + getToken());
            request.addHeader("Content-Type", "application/octet-stream");
            InputStream inputStream = file.getInputStream();

            byte[] byt = new byte[inputStream.available()];
            inputStream.read(byt);
            request.setEntity(new ByteArrayEntity(byt, ContentType.create("image/jpg")));
            response = httpclient.execute(request);
            HttpEntity httpEntity = response.getEntity();
            String result = EntityUtils.toString(httpEntity, "UTF-8");// 转成string
            JSONObject jso = JSONObject.parseObject(result);
            Object errcode = jso.get("errcode");
            int errCode = (int) errcode;
            if (errCode == 0) {
                return true;
            } else if (errCode == 87014) {
                return false;
            }else{
                return false;
            }
        } catch (Exception e) {
            e.printStackTrace();
//            System.out.println("----------------调用腾讯内容过滤系统出错------------------");
            return true;
        }
    }

    public static void main(String[] args) {
        try {
            System.out.println(WxNoun.checkMsg("111"));
        } catch (HttpException e) {
            e.printStackTrace();
        }
    }
}
